package com.rc.saas.tenant.controller.order;

import com.alibaba.excel.EasyExcel;
import com.github.pagehelper.PageInfo;
import com.rc.saas.tenant.base.WebPageInfo;
import com.rc.saas.tenant.common.redis.RedisLoader;
import com.rc.saas.tenant.common.utils.StringUtil;
import com.rc.saas.tenant.common.vo.TResponse;
import com.rc.saas.tenant.model.his.HisExceptionOrderInfo;
import com.rc.saas.tenant.model.operator.TenantOperator;
import com.rc.saas.tenant.model.operator.TenantOperatorStation;
import com.rc.saas.tenant.model.operator.TenantOperatorStationExample;
import com.rc.saas.tenant.model.order.*;
import com.rc.saas.tenant.model.tenant.TenantUser;
import com.rc.saas.tenant.search.operator.OperatorSearch;
import com.rc.saas.tenant.search.order.ExceptionOrderInfoSearch;
import com.rc.saas.tenant.service.his.HisExceptionOrderInfoService;
import com.rc.saas.tenant.service.operator.TenantOperatorService;
import com.rc.saas.tenant.service.operator.TenantOperatorStationService;
import com.rc.saas.tenant.service.order.ExceptionOrderInfoService;
import com.rc.saas.tenant.service.order.OrderInfoService;
import com.rc.saas.tenant.shiro.ShiroUtils;
import com.rc.saas.tenant.util.ExportUtils;
import com.rc.saas.tenant.vo.order.ExceptionOrderPrintVo;
import com.rc.saas.tenant.vo.order.OrderResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Controller
@RequestMapping("/exceptionOrder")
public class ExceptionOrderInfoController {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private ExceptionOrderInfoService exceptionOrderInfoService;

    @Autowired
    private OrderInfoService orderInfoService;

    @Autowired
    private TenantOperatorService tenantOperatorService;

    @Autowired
    private RedisLoader redisLoader;

    @Autowired
    private HisExceptionOrderInfoService hisExceptionOrderInfoService;

    @Autowired
    private TenantOperatorStationService tenantOperatorStationService;

    /**
     * 跳转运营商异常订单修复记录页面
     *
     * @param model
     * @return
     */
    @RequestMapping(value = "/index", method = RequestMethod.GET)
    public String exceptionOrderInfoPage(Model model) {
        return "/templates/order/orderInfo/exceptionOrderInfo";
    }

    /**
     * 返回异常订单修复记录列表数据
     *
     * @return
     */
    @RequestMapping(value = "/listExceptionOrderInfo", method = RequestMethod.GET)
    @ResponseBody
    public WebPageInfo listOrderInfo(ExceptionOrderInfoSearch exceptionOrderInfoSearch) {
        PageInfo<OrderResult> pageInfo = orderInfoService.listByExceptionOrderCondition(exceptionOrderInfoSearch);
        WebPageInfo webPageInfo = new WebPageInfo(pageInfo.getList(), Long.valueOf(pageInfo.getTotal()).intValue());
        return webPageInfo;
    }

    /**
     * 保存异常订单修复记录
     *
     * @return
     */
    @RequestMapping(value = "/saveExceptionOrderInfo", method = RequestMethod.POST)
    @ResponseBody
    public TResponse saveOrUpdateExceptionOrderInfo(ExceptionOrderInfo exceptionOrderInfo) {
        TenantUser user = ShiroUtils.getSessionUser();
        try {
            OrderInfo orderInfo = orderInfoService.selectByPrimaryKey(exceptionOrderInfo.getOrderId());
            if (orderInfo != null) {
                HisExceptionOrderInfo hisExceptionOrderInfo=hisExceptionOrderInfoService.selectByPrimaryKey(orderInfo.getOrderId());
                if (hisExceptionOrderInfo==null){
                    //保存异常订单历史记录
                    HisExceptionOrderInfo hisExceptionOrderInfo1=new HisExceptionOrderInfo();
                    BeanUtils.copyProperties(orderInfo, hisExceptionOrderInfo1);
                    hisExceptionOrderInfoService.insertSelective(hisExceptionOrderInfo1);
                }


                if ("2".equals(orderInfo.getHlhtOrderType()) && StringUtil.isNotBlank(orderInfo.getHlhtTenantCode())) {
                    HlhtOrderInfo hlhtOrderInfo = orderInfoService.selectHlhtOrderInfoByOrderId(orderInfo.getOrderId());
                    exceptionOrderInfo.setTenantCode(hlhtOrderInfo.getTenantCode());
                } else {
                    exceptionOrderInfo.setTenantCode(orderInfo.getTenantCode());
                }
                TenantOperatorStationExample tenantOperatorStationExample=new TenantOperatorStationExample();
                tenantOperatorStationExample.createCriteria().andTenantCodeEqualTo(user.getTenantCode()).andElecStationIdEqualTo(exceptionOrderInfo.getElecStationId());
                List<TenantOperatorStation> tenantOperatorStations=tenantOperatorStationService.selectByExample(tenantOperatorStationExample);
                if (!CollectionUtils.isEmpty(tenantOperatorStations)){
                    //exceptionOrderInfo.setTenantOperatorCode(tenantOperatorStations.stream().map(tenantOperatorStation -> tenantOperatorStation.getTenantOperatorCode())));
                    List<String> tenantOperatorCodes=tenantOperatorStations.stream().map(tenantOperatorStation -> tenantOperatorStation.getTenantOperatorCode()).collect(Collectors.toList());
                    String tenantOperatorCode="";
                    for (int i = 0; i <tenantOperatorCodes.size() ; i++) {
                        if (i==tenantOperatorCodes.size()-1){
                            tenantOperatorCode+=tenantOperatorCodes.get(i);
                        } else {
                            tenantOperatorCode+=tenantOperatorCodes.get(i)+",";
                        }
                    }
                    exceptionOrderInfo.setTenantOperatorCode(tenantOperatorCode);
                }
                exceptionOrderInfo.setOrderId(orderInfo.getOrderId());
                exceptionOrderInfo.setDiffElecMoney(orderInfo.getTotalElecMoney().subtract(exceptionOrderInfo.getTotalElecMoney()));
                //服务费差值=原订单服务费-登记服务费-优惠
                exceptionOrderInfo.setDiffServiceMoney(orderInfo.getTotalSeviceMoney().subtract(exceptionOrderInfo.getTotalServiceMoney()).subtract(exceptionOrderInfo.getDiscountAmount()));
                exceptionOrderInfo.setElecStationId(orderInfo.getElecStationId());
                exceptionOrderInfo.setCreatedBy(user.getLoginName());
                exceptionOrderInfo.setCreatedTime(new Date());
                exceptionOrderInfo.setLastUpdatedBy(user.getLoginName());
                //生成异常订单记录
                if (exceptionOrderInfo.getExceptionOrderInfoId() == null) {
                    exceptionOrderInfoService.insertSelective(exceptionOrderInfo);
                } else {
                    exceptionOrderInfoService.updateByPrimaryKeySelective(exceptionOrderInfo);
                }
                return TResponse.SUCCESS();
            } else {
                return TResponse.FAIL("订单数据不存在");
            }
        } catch (Exception e) {
            logger.error("保存异常订单修复记录失败", e);
            return TResponse.FAIL("操作失败");
        }
    }

    /**
     * 运营商所属分销商
     *
     * @return
     */
    @RequestMapping(value = "/listTenantOperator", method = RequestMethod.GET)
    @ResponseBody
    public TResponse listTenantOperator() {
        TenantUser user = ShiroUtils.getSessionUser();
        try {
            OperatorSearch operatorSearch = new OperatorSearch();
            operatorSearch.setTenantCode(user.getTenantCode());
            List<TenantOperator> list = tenantOperatorService.listExportTenantOperator(operatorSearch);
            return TResponse.SUCCESS_DATA(list);
        } catch (Exception e) {
            logger.error("查询运营商所属分销商失败", e);
            return TResponse.FAIL("操作失败");
        }
    }

    /**
     * 修改异常订单状态
     *
     * @param exceptionOrderInfoId
     * @param rejectionReason
     * @param status
     * @return
     */
    @RequestMapping(value = "/updateExceptionOrderStatus", method = RequestMethod.POST)
    @ResponseBody
    public TResponse updateExceptionOrderStatus(Long exceptionOrderInfoId, String rejectionReason, String status) {
        TenantUser tenantUser = ShiroUtils.getSessionUser();
        //status:0,待复核；1，待修复；2，待核销；3，待入账；4，已入账；5，已驳回；6，已完成
        try {
            ExceptionOrderInfo exceptionOrderInfo = exceptionOrderInfoService.selectByPrimaryKey(exceptionOrderInfoId);
            if ("2".equals(status)) {
                //异常订单修复时间
                exceptionOrderInfo.setRepairTime(new Date());
            } else if ("5".equals(status)) {
                if (StringUtil.isBlank(rejectionReason)) {
                    return TResponse.FAIL("请输入驳回原因");
                }
                //异常订单复核或修复前驳回原因
                exceptionOrderInfo.setRejectionReason(rejectionReason);
            }
            exceptionOrderInfo.setStatus(status);
            exceptionOrderInfo.setLastUpdatedBy(tenantUser.getLoginName());
            exceptionOrderInfo.setLastUpdatedTime(new Date());
            exceptionOrderInfoService.updateByPrimaryKeySelective(exceptionOrderInfo);
            return TResponse.SUCCESS();
        } catch (Exception e) {
            logger.error("修改异常订单状态失败", e);
            return TResponse.FAIL("修改异常订单状态失败");
        }
    }

    /**
     * 导出异常订单修复记录列表
     *
     * @param exceptionOrderInfoSearch
     * @param response
     * @return
     */
    @RequestMapping("/exportExceptionOrderInfo")
    @ResponseBody
    public TResponse exportExceptionOrderInfo(ExceptionOrderInfoSearch exceptionOrderInfoSearch, HttpServletResponse response) {

        ExportUtils.setDefaultPaging(exceptionOrderInfoSearch);
        if (exceptionOrderInfoSearch.getCount() == 0 || exceptionOrderInfoSearch.getCount() == null) {
            exceptionOrderInfoSearch.setCount(exceptionOrderInfoSearch.getLimit());
        }

        if (exceptionOrderInfoSearch.getCount() > 150000) {
            return TResponse.FAIL("最多导出十五万数据");
        }

        if (exceptionOrderInfoSearch.getCount() >= 100000) {
            String exportData = (String) redisLoader.get("saas:exportData");
            if (exportData != null) {
                return TResponse.FAIL("导出人数过多,请稍后重试");
            }
            TenantUser user = ShiroUtils.getSessionUser();
            redisLoader.set("saas:exportData", user.getTenantCode(), 1000 * 20);
        }
        //导出拼接开始条数
        exceptionOrderInfoSearch.setOffset(exceptionOrderInfoSearch.getLimit() * (exceptionOrderInfoSearch.getOffset() - 1));
        TenantUser tenantUser = ShiroUtils.getSessionUser();
        exceptionOrderInfoSearch.setTenantOperatorCode(tenantUser.getTenantOperatorCode());
        List<ExceptionOrderPrintVo> exceptionOrderPrintVos = orderInfoService.exportExceptionOrderInfo(exceptionOrderInfoSearch);
        response.setHeader("Set-Cookie", "fileDownload=true; path=/");
        try {

            logger.info(exceptionOrderInfoSearch.getTenantCode() + ",orderInfo/exportExceptionOrderInfo,startTime:{},endTime:{},count:{}",
                    exceptionOrderInfoSearch.getStartTime(), exceptionOrderInfoSearch.getEndTime(), exceptionOrderInfoSearch.getCount());

            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileName = URLEncoder.encode("异常订单列表", "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
            EasyExcel.write(response.getOutputStream(), ExceptionOrderPrintVo.class).sheet("异常订单列表").doWrite(exceptionOrderPrintVos);
            return TResponse.SUCCESS();
        } catch (Exception e) {
            logger.error("导出异常订单失败", e.getMessage());
            return TResponse.FAIL(e.getMessage());
        }
    }

    /**
     * 跳转分销商异常订单修复记录页面
     *
     * @param model
     * @return
     */
    @RequestMapping(value = "/operator/index", method = RequestMethod.GET)
    public String operatorExceptionOrderInfoPage(Model model) {
        return "/templates/order/orderInfo/operatorExceptionOrderInfo";
    }

    /**
     * 返回分销商异常订单列表数据
     *
     * @return
     */
    @RequestMapping(value = "/listPageOperatorExceptionOrderInfo", method = RequestMethod.GET)
    @ResponseBody
    public WebPageInfo listPageOperatorExceptionOrderInfo(ExceptionOrderInfoSearch orderSearch) {
        TenantUser user = ShiroUtils.getSessionUser();
        orderSearch.setTenantOperatorCode(user.getTenantOperatorCode());
        PageInfo<OrderResult> pageInfo = orderInfoService.listPageOperatorExceptionOrderInfo(orderSearch);
        WebPageInfo webPageInfo = new WebPageInfo(pageInfo.getList(), Long.valueOf(pageInfo.getTotal()).intValue());
        return webPageInfo;
    }

    /**
     * 导出分销商异常订单修复记录列表
     *
     * @param exceptionOrderInfoSearch
     * @param response
     * @return
     */
    @RequestMapping("/exportOperatorExceptionOrderInfo")
    @ResponseBody
    public TResponse exportOperatorExceptionOrderInfo(ExceptionOrderInfoSearch exceptionOrderInfoSearch, HttpServletResponse response) {
        ExportUtils.setDefaultPaging(exceptionOrderInfoSearch);
        if (exceptionOrderInfoSearch.getCount() == 0 || exceptionOrderInfoSearch.getCount() == null) {
            exceptionOrderInfoSearch.setCount(exceptionOrderInfoSearch.getLimit());
        }

        if (exceptionOrderInfoSearch.getCount() > 150000) {
            return TResponse.FAIL("最多导出十五万数据");
        }

        if (exceptionOrderInfoSearch.getCount() >= 100000) {
            String exportData = (String) redisLoader.get("saas:exportData");
            if (exportData != null) {
                return TResponse.FAIL("导出人数过多,请稍后重试");
            }
            TenantUser user = ShiroUtils.getSessionUser();
            redisLoader.set("saas:exportData", user.getTenantCode(), 1000 * 20);
        }
        //导出拼接开始条数
        exceptionOrderInfoSearch.setOffset(exceptionOrderInfoSearch.getLimit() * (exceptionOrderInfoSearch.getOffset() - 1));
        TenantUser tenantUser = ShiroUtils.getSessionUser();
        exceptionOrderInfoSearch.setTenantOperatorCode(tenantUser.getTenantOperatorCode());
        List<ExceptionOrderPrintVo> exceptionOrderPrintVos = orderInfoService.exportOperatorExceptionOrderInfo(exceptionOrderInfoSearch);
        response.setHeader("Set-Cookie", "fileDownload=true; path=/");
        try {

            logger.info(exceptionOrderInfoSearch.getTenantCode() + ",orderInfo/exportExceptionOrderInfo,startTime:{},endTime:{},count:{}",
                    exceptionOrderInfoSearch.getStartTime(), exceptionOrderInfoSearch.getEndTime(), exceptionOrderInfoSearch.getCount());

            response.setContentType("application/vnd.ms-excel");
            response.setCharacterEncoding("utf-8");
            // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
            String fileName = URLEncoder.encode("分销商异常订单列表", "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
            EasyExcel.write(response.getOutputStream(), ExceptionOrderPrintVo.class).sheet("分销商异常订单列表").doWrite(exceptionOrderPrintVos);
            return TResponse.SUCCESS();
        } catch (Exception e) {
            logger.error("导出分销商异常订单失败", e.getMessage());
            return TResponse.FAIL(e.getMessage());
        }
    }
}
